/**
 * API请求基础模块
 * 集成认证和拦截器，统一处理请求响应
 */
import axios, { AxiosResponse, AxiosError } from 'axios';
import auth from '../utils/auth';
import { MESSAGES } from '../constants/common';

// 创建axios实例
const api = axios.create({
  baseURL: '/adminapi',
  timeout: 10000, // 10秒超时
  headers: {
    'Content-Type': 'application/json',
  }
});

// 请求拦截器
api.interceptors.request.use(
  (config) => {
    // 从auth获取token并添加到请求头
    const token = auth.getToken();
    if (token && config.headers) {
      config.headers.Authorization = token;
      
      // 添加用户角色信息和区域信息到请求头
      const userInfo = auth.getUserInfo();
      if (userInfo) {
        // 确保roleId和region值有效
        const roleId = userInfo.roleId || '';
        const region = userInfo.region || '';
        
        // 记录当前请求信息
        console.log(`请求URL: ${config.url}，方法: ${config.method}`);
        console.log(`用户角色: ${roleId}, 区域: ${region}`);
        
        // 添加到请求头
        config.headers['X-User-Role'] = roleId;
        config.headers['X-User-Region'] = region;
        
        // 将用户信息添加到query参数中(对于GET请求)
        if (config.method?.toLowerCase() === 'get') {
          // 确保params是一个对象
          config.params = {
            ...(config.params || {}),
            roleId,
            region
          };
        }
        
        // 对于POST、PUT、PATCH请求，将用户信息添加到请求体
        if (['post', 'put', 'patch'].includes(config.method?.toLowerCase() || '') && 
            config.data && typeof config.data === 'object') {
            
          // 如果是FormData类型，直接添加字段
          if (config.data instanceof FormData) {
            if (!config.data.has('roleId')) config.data.append('roleId', String(roleId));
            if (!config.data.has('region')) config.data.append('region', String(region));
          } 
          // 如果是普通对象，合并数据
          else if (!(config.data instanceof ArrayBuffer) && 
                   !(config.data instanceof File) && 
                   !(config.data instanceof Blob)) {
            try {
              // 对于JSON格式的请求体
              const contentType = config.headers['Content-Type'];
              if (contentType && typeof contentType === 'string' && contentType.includes('application/json')) {
                // 如果是字符串形式的JSON
                if (typeof config.data === 'string') {
                  try {
                    const parsedData = JSON.parse(config.data);
                    config.data = JSON.stringify({
                      ...parsedData,
                      roleId: parsedData.roleId || roleId,
                      region: parsedData.region || region
                    });
                  } catch (e) {
                    console.warn('无法解析请求体JSON', e);
                  }
                } 
                // 如果是对象
                else {
                  config.data = {
                    ...config.data,
                    roleId: config.data.roleId || roleId,
                    region: config.data.region || region
                  };
                }
              }
            } catch (error) {
              console.warn('添加用户信息到请求体时出错', error);
            }
          }
        }
      } else {
        console.warn('未找到用户信息，请求可能会被拒绝');
      }
    } else {
      console.warn('未找到认证令牌，请求可能会被拒绝');
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
api.interceptors.response.use(
  (response) => {
    // 提取可能包含的新token
    const newToken = response.headers['x-auth-token'] || 
                     response.headers['authorization'] ||
                     (response.data && typeof response.data === 'object' && 'token' in response.data ? 
                     response.data.token as string : undefined);
    
    // 自动保存新token
    if (newToken) {
      auth.setToken(newToken);
    }
    
    return response;
  },
  (error: AxiosError) => {
    // 辅助函数 - 安全地获取错误消息
    const getErrorMessage = (data: unknown, status: number): string => {
      if (data && typeof data === 'object' && 'msg' in data) {
        return String(data.msg);
      }
      return `请求失败 (${status})`;
    };
    
    // 统一处理HTTP错误
    if (error.response) {
      switch (error.response.status) {
        case 400:
          console.error('请求参数错误');
          break;
        case 401:
          // 未授权，可能是token过期
          console.warn(MESSAGES.AUTH.SESSION_EXPIRED);
          
          // 清除用户信息
          auth.clearUserInfo();
          
          // 重定向到登录页
          setTimeout(() => {
            window.location.href = '/login';
          }, 1500);
          break;
        case 403:
          console.error(MESSAGES.AUTH.PERMISSION_DENIED);
          break;
        case 404:
          console.error('请求的资源不存在');
          break;
        case 500:
          console.error('服务器内部错误');
          break;
        default:
          // 使用辅助函数获取错误信息
          console.error(getErrorMessage(error.response.data, error.response.status));
      }
    } else if (error.request) {
      // 请求发出但没有收到响应
      console.error('网络错误，请检查网络连接');
    } else {
      // 请求配置出错
      console.error(`请求错误: ${error.message}`);
    }
    return Promise.reject(error);
  }
);

/**
 * 提取API响应数据
 * @param response Axios响应对象
 * @returns 响应数据
 */
export const extractData = <T>(response: AxiosResponse): T => {
  // 检查响应是否有data属性
  if (!response.data) {
    throw new Error('响应数据为空');
  }
  
  // 情况1: 后端直接返回数组形式数据 (用于角色和区域列表)
  if (Array.isArray(response.data)) {
    return response.data as T;
  }
  
  // 情况2: 标准响应格式 {code: 200/201, data: xxx}
  if (typeof response.data === 'object' && 
      'code' in response.data && 
      (response.data.code === 200 || response.data.code === 201)) {
    
    // 如果有data字段就返回它
    if ('data' in response.data) {
      return response.data.data as T;
    }
    
    // 没有data字段但状态码为200/201，返回整个响应
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { code, msg, ...rest } = response.data;
    if (Object.keys(rest).length > 0) {
      return rest as T;
    }
    
    // 空对象情况
    return {} as T;
  }
  
  // 处理错误情况
  const errorMsg = typeof response.data === 'object' && 
                  'msg' in response.data ? 
                  response.data.msg as string : 
                  '数据获取失败';
  throw new Error(errorMsg);
};

export default api;